package com.summer.filesync.sync;

import java.io.Serializable;

/** 文件事件 表示文件系统中发生的变化事件 */
public class FileEvent implements Serializable {
  private static final long serialVersionUID = 1L;

  public enum EventType {
    CREATED, // 文件/目录创建
    MODIFIED, // 文件/目录修改
    DELETED, // 文件/目录删除
    RENAMED // 文件/目录重命名
  }

  private EventType type; // 事件类型
  private String filePath; // 文件路径
  private String oldPath; // 重命名前的路径（仅用于RENAMED事件）
  private long timestamp; // 事件发生时间
  private String checksum; // 文件校验和（如果是文件）
  private long fileSize; // 文件大小
  private boolean isDirectory; // 是否为目录
  private String nodeId; // 产生事件的节点ID

  public FileEvent() {
    this.timestamp = System.currentTimeMillis();
  }

  public FileEvent(EventType type, String filePath) {
    this();
    this.type = type;
    this.filePath = filePath;
  }

  public FileEvent(EventType type, String filePath, String oldPath) {
    this(type, filePath);
    this.oldPath = oldPath;
  }

  /** 创建文件创建事件 */
  public static FileEvent createFileCreated(
      String filePath, long fileSize, String checksum, boolean isDirectory) {
    FileEvent event = new FileEvent(EventType.CREATED, filePath);
    event.setFileSize(fileSize);
    event.setChecksum(checksum);
    event.setDirectory(isDirectory);
    return event;
  }

  /** 创建文件修改事件 */
  public static FileEvent createFileModified(String filePath, long fileSize, String checksum) {
    FileEvent event = new FileEvent(EventType.MODIFIED, filePath);
    event.setFileSize(fileSize);
    event.setChecksum(checksum);
    event.setDirectory(false);
    return event;
  }

  /** 创建文件删除事件 */
  public static FileEvent createFileDeleted(String filePath, boolean isDirectory) {
    FileEvent event = new FileEvent(EventType.DELETED, filePath);
    event.setDirectory(isDirectory);
    return event;
  }

  /** 创建文件重命名事件 */
  public static FileEvent createFileRenamed(String oldPath, String newPath, boolean isDirectory) {
    FileEvent event = new FileEvent(EventType.RENAMED, newPath, oldPath);
    event.setDirectory(isDirectory);
    return event;
  }

  /** 检查是否为文件事件（非目录） */
  public boolean isFileEvent() {
    return !isDirectory;
  }

  /** 检查是否为目录事件 */
  public boolean isDirectoryEvent() {
    return isDirectory;
  }

  /** 获取事件描述 */
  public String getDescription() {
    StringBuilder sb = new StringBuilder();
    sb.append(type.name()).append(" ");
    sb.append(isDirectory ? "directory" : "file").append(" ");
    sb.append(filePath);

    if (type == EventType.RENAMED && oldPath != null) {
      sb.append(" (from ").append(oldPath).append(")");
    }

    return sb.toString();
  }

  /** 检查事件是否相等（基于路径和类型） */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null || getClass() != obj.getClass()) return false;

    FileEvent fileEvent = (FileEvent) obj;
    return type == fileEvent.type
        && java.util.Objects.equals(filePath, fileEvent.filePath)
        && java.util.Objects.equals(oldPath, fileEvent.oldPath);
  }

  @Override
  public int hashCode() {
    return java.util.Objects.hash(type, filePath, oldPath);
  }

  @Override
  public String toString() {
    return "FileEvent{"
        + "type="
        + type
        + ", filePath='"
        + filePath
        + '\''
        + (oldPath != null ? ", oldPath='" + oldPath + '\'' : "")
        + ", timestamp="
        + timestamp
        + ", fileSize="
        + fileSize
        + ", isDirectory="
        + isDirectory
        + ", nodeId='"
        + nodeId
        + '\''
        + '}';
  }

  // Getters and Setters
  public EventType getType() {
    return type;
  }

  public void setType(EventType type) {
    this.type = type;
  }

  public String getFilePath() {
    return filePath;
  }

  public void setFilePath(String filePath) {
    this.filePath = filePath;
  }

  public String getOldPath() {
    return oldPath;
  }

  public void setOldPath(String oldPath) {
    this.oldPath = oldPath;
  }

  public long getTimestamp() {
    return timestamp;
  }

  public void setTimestamp(long timestamp) {
    this.timestamp = timestamp;
  }

  public String getChecksum() {
    return checksum;
  }

  public void setChecksum(String checksum) {
    this.checksum = checksum;
  }

  public long getFileSize() {
    return fileSize;
  }

  public void setFileSize(long fileSize) {
    this.fileSize = fileSize;
  }

  public boolean isDirectory() {
    return isDirectory;
  }

  public void setDirectory(boolean directory) {
    isDirectory = directory;
  }

  public String getNodeId() {
    return nodeId;
  }

  public void setNodeId(String nodeId) {
    this.nodeId = nodeId;
  }
}
